#!/usr/bin/env perl
##
$VER="1.3" ;
# nopen seems happier with stderr in lsh runs
# or does it? Took it out now...
#select STDERR ;
$| = 1 ;
myinit() ;
foreach (@ARGV) {
  # quietly throw away any args not IPs
  push(@scanips,$_) if ipcheck($_) ;
}
if (!@scanips) {
  if (@broadcasts) {
    $prompt = "Enter any additional address(es) or broadcast(s) to scan, whitespace delimited,
<A>bort, or just hit return to continue:" ;
    $it = "it" ;
    if (@broadcasts > 1) {
      $es = "es" ;
      $it = "them" ;
    }
    progprint("Found broadcast address$es for $nopen_rhostname:\n\n@broadcasts\n\n
Will be issuing following scans on $it: @doscans\n\n");
  } else {
    $prompt = "Enter the address(es) or broadcast(s) to scan (with @doscans),
whitespace delimited, or just hit return to exit:"
  }
  if ($_ = getinput($prompt)) {
    mydie("Aborting") if (/^a/i) ;
    foreach (split) {
      push(@broadcasts,$_) if ipcheck($_) ;
    }
  }
}
if (@scanips) {
  my $s = "s\n" if (@broadcasts > 1) ;
  $ans = getinput("Scanning @scanips already.\n".
		  "Do you also want to scan broadcast$s (@broadcasts)?","N") ;
  @broadcasts = () unless ($ans =~ /^y/i) ;
}
foreach $ip (@scanips) {
  foreach $sploit (@doscans) {
    $doscans .= "-scan $sploit $ip one\n" ;
  }
}
foreach $ip (@broadcasts) {
  foreach $sploit (@doscans) {
    $doscans .= "-scan $sploit $ip\n" ;
  }
}
if ($doscans) {
  progprint("\nWriting scan script with:\n$doscans\n") ;
  if (open (OUT,">> $opetc/nopen_auto.$nopen_mypid.$ext")) {
#    print OUT ("#NOGS\n-lsh mv $opetc/nopen_auto.$nopen_mypid $opetc/nopen_auto.$nopen_mypid.last\n") ;
    print OUT ("#NOGS\n") ;
    print OUT $doscans ;
    foreach (@scanips) {
      my $more .= " $_" unless $broadcasts{$_} ;
    }
    unless ($calledfromautosploit) {
      $ans2 = getinput("Then proceed with -gs sploit${more}?","N") ;
      if ($ans2 =~ /^y/i) {
	print OUT "-gs sploit @scanips\n" ;
	progprint("\nAdding sploit after scans with: -gs sploit @scanips\n") ;
      }
    } else {
      progprint("\nAdding sploit after scans with: -gs sploit @scanips FROMAUTOSCANS\n") ;
      print OUT "-gs sploit @scanips FROMAUTOSCANS\n" ;
    }
    close(OUT) ;
    rename("$opetc/nopen_auto.$nopen_mypid.$ext","$opetc/nopen_auto.$nopen_mypid");
  } else {
    mydie("Could not write to $opetc/nopen_auto.$nopen_mypid.$ext");
  }
  exit ;
}#if ($doscans)
#ENDMAIN
sub mywarn {
  local ($what,$color,$color2,$what2) = (@_) ;
  $color = $COLOR_WARNING unless $color ;
  $color2 = $color unless $color2 ;
  $what2 = " $what2" if ($what2) ;
#  local (@stuff) = (@_,$hopping) ;
  warn  "${color2}${prog}[$$]$what2\a: ${color}$what$COLOR_NORMAL\n" ;
#  warn "\n${COLOR_WARNING}\a@_$COLOR_NORMAL\n" ;
}#mywarn

sub mydie {
  local ($what,$color,$color2,$what2) = (@_) ;
  $color = $COLOR_FAILURE unless $color ;
  $color2 = $color unless $color2 ;
  $what2 = " $what2" if ($what2) ;
#  local (@stuff) = (@_,$hopping) ;
  warn  "${color2}${prog}[$$]$what2\a: ${color}$what$COLOR_NORMAL\n" ;
#"\n${COLOR_FAILURE}\a$what $hopping$COLOR_NORMAL\n" ;
  exit 1;
}#mydie

sub usage {
  print "\nFATAL ERROR: @_\n" if ( @_ );
  $usagetext = $gsusagetext if ($nopen_mypid) ;
  print $usagetext unless $opt_v ;
  print $vertext ;
  print "\nFATAL ERROR: @_\n" if ( @_ );
  exit;
}#usage

sub myinit {
  use File::Basename ;
  require "getopts.pl";
  $COLOR_SUCCESS="\033[1;32m";
  $COLOR_FAILURE="\033[1;31m";
  $COLOR_WARNING="\033[1;33m";
  $COLOR_NORMAL="\033[0;39m";
  $COLOR_NOTE="\033[0;34m";
  $prog = basename $0 ;
  $vertext = "$prog version $VER\n" ;
  $| = 1;
  $nopen_mypid = $ENV{NOPEN_MYPID} ;
  $nopen_mylog = $ENV{NOPEN_MYLOG} ;
  $nopen_rhostname = $ENV{NOPEN_RHOSTNAME} ;
  mydie("No user servicable parts inside.\n".
	"(I.e., noclient calls $prog, not you.)\n".
	"$vertext") unless $nopen_rhostname;
  $opdir = "/current" ;
  $opbin = "$opdir/bin" ;
  $opetc = "$opdir/etc" ;
  $opdown = "$opdir/down" ;
  $ext = "$$" ; # some uniqueness to me
  @doscans = (brpc,rpc,xwin,mibiisa) ;
#faster this way but no bs/ys
#  @doscans = (mibiisa) ;
  foreach (@ARGV) {
      # quietly throw away any args not IPs
      $GSOPTIONS .= "$_ " if (ipcheck($_)) ;
      $calledfromautosploit++ if ($_ eq "FROMAUTOSPLOIT") ;
      $calledfromautoscans++ if ($_ eq "FROMAUTOSCANS") ;
  }
  @broadcasts = split(/\n/,`grep "Broadcast" /current/down/hostinfo.$nopen_rhostname 2>/dev/null | awk '{print \$2}'`) ;
  $broadcasts{$_}++ foreach (@broadcasts) ;
  $usagetext="
Usage: $prog [-h]                       (prints this usage statement)

NOT CALLED DIRECTLY

$prog is run from within a NOPEN session via when \"-gs scans\" is used.

";
  if (@broadcasts) {
    $broadcaststring = " (@broadcasts)." ;
  } else {
    $broadcaststring = ",$COLOR_FAILURE which cannot be determined!\n
Was hostinfo.$nopen_rhostname built successfully by autodone?$COLOR_NORMAL";
  }
  $gsusagetext="
Usage: -gs scans [-h] [ IP1 [ IP2 ... ] ]

-gs scans calls $opetc/autoscans [ IP1 [ IP2 ... ] ].

When one or more IPs are given, you are also asked if you wish
to scan the broadcast address(es)$broadcaststring

With no arguments, -gs scans will scan the broadcast address(es),
as well as your choice of other IPs/broadcasts, with these scans:
      @doscans

For any other scans, use the usual \"-scan what where\" syntax.

";
  mydie("bad option(s)") if (! Getopts( "hv" ) ) ;
  usage() if ($opt_h or $opt_v) ;
}#myinit

sub progprint {
  local ($what,$color,$color2,$what2) = (@_) ;
  $color = $COLOR_NOTE unless $color ;
  $color2 = $color unless $color2 ;
  $what2 = " $what2" if ($what2) ;
#  select STDERR ;
  $| = 1;
  print "${color2}${prog}[$$]$what2: ${color}$what$COLOR_NORMAL\n" ;
}#progprint
sub getinput {
  local($prompt,$default,@allowed) = @_;
  local($ans,$tmp,%other) = ();
  $other{"Y"} = "N" ; $other{"N"} = "Y" ;
  if ($other{$default} and ! (@allowed)) {
    push(@allowed,$other{$default}) ;
  }
  $tmp = $default;
  if (chop($tmp) eq "
") {
    #damn ^M's in script files
    $default = $tmp;
  }
  SUB: while (1) {
    print STDERR $prompt;
    if ($default) {
      print STDERR " [$default] ";
    } else {
      print STDERR " ";
    }
    chomp($ans = <STDIN>);
    $ans = $default if ( $ans eq "" );
    last SUB if ($#allowed < 0) ;
    foreach ($default,@allowed) {
      last SUB if $ans =~ /^$_/i ;
    }
  }
  return $ans;
}#getinput

sub ipcheck() {
  # returns 1 iff $ipstr is in dotted decimal notation with each 
  # octet between 0 and 255 inclusive (i.e. 0.0.0.0 and 255.255.255.255 are valid)
  local($ipstr,@junk) = @_;
  # need -1 in following split to keep null trailing fields (to reject "1.2.3.4.")
  @octets=split(/\./,$ipstr,-1);
  return 0 if ($#octets != 3);
  foreach (@octets) {
    # return 0 if (empty or nondigits or <0 or >255)
    return 0 if ($_ eq "" || ( /\D/ ) || $_ < 0 || $_ > 255);
  }
  return 1;
}#pcheck
